<?php
namespace App\Service\BMR;
use Illuminate\Support\Facades\Cache;

class BMR_Food {
    protected $url = 'http://yingyang.118cha.com/';
    protected $html;
    protected static $keys;
   const CACHE_KEY = 'BMR_Food';

    /**标签正则
     * $param string $tag 标签名
     * @param bool $isSingle 是否单标签
     * @return string
     */
    public function tagPatter($tag, $isSingle = false)
    {
        return !$isSingle
            ? "/<{$tag}(.+?)>(.+?)<\/{$tag}>/ius"  //开始结束标签
            : "<{$tag}(.+?)>";                      //单标签
    }

    /*
     * 获取标题数组
     * @return array
     */
    public static function keys()
    {
        if (!static::$keys) {
            static::$keys = config('bmr.food.keys');
        }
        return static::$keys;
    }

    /**获取标题的英文标识
     * @return array
     */
    public static function getKeysEn()
    {
        return array_column(static::keys(), 'en');
    }

    /**获取标题中文标识
     * @return array
     */
    public static function getKeysZh()
    {
        return array_column(static::keys(), 'zh');
    }

    /**
     * 以标题英文键作为key，中文作为value
     * @reutrn array
     * [
     *    'category' => '类别'
     * ]
     */
    public static function getKeysEnZh()
    {
        return array_combine(static::getKeysEn(), static::getKeysZh());
    }
    /**
     * 以标题中文键作为key，英文作为value
     * @reutrn array
     * [
     *    '类别' => 'category'
     * ]
     */
    public static function getKeysZhEn()
    {
        return array_combine(static::getKeysZh(), static::getKeysEn());
    }

    /**设置缓存文件夹
     * @param $file
     * @throws Exception
     */
    public function setCacheFile($file)
    {
        if (!is_file($file)) {
            throw new \Exception("{$file} 不是一个文件, 无法设置缓存", 400);
        }
        $this->cacheFile = $file;
    }


    /**获取要采集的html数据
     * @return string
     * @throws \Exception
     */
    public function getHtml()
    {
        if (!$this->html) {
            //没缓存
            if (is_null($cache = $this->getCache())) {
                //设置缓存
                $cache = @file_get_contents($this->url);
                if (!empty($cache))
                    $this->setCache($cache);
            }
            //获取缓存
            $this->html = $cache;
        }
        if (!$this->html) {
            throw new \Exception('采集的页面无法访问', '400');
        }
        return $this->html;
    }

    /**获取缓存
     * @return string
     */
    public function getCache() {
        $cache = Cache::get(static::CACHE_KEY);
        return $cache ? $cache : null;
    }

    /**设置缓存
     * @param $data
     * @return int
     */
    protected function setCache($data) {
        Cache::put(static::CACHE_KEY, $data);
    }


    /**获取要被采集的数据
     * @return string
     */
    public function getTable()
    {
        $return = [];
        $data = $this->getHtml();
        //查找第一个table
        preg_match_all($this->tagPatter('table'), $data, $result);
        if (!isset($result[2][0])) {
            return $return;
        }
        $table   = $result[2][0];
        //查找tr标签
        preg_match_all($this->tagPatter('tr'), $table, $trResult);
        if (!isset($trResult[0][0])) {
            return $return;
        }
        $trList = $trResult[0];
        $tdPattern = $this->tagPatter('td');
        //英文标题
        $keys = static::getKeysEn();
        $keyLength = count($keys);
        //初始化每个tr标签内容
        foreach($trList as $line => $tr) {
            //跳过第一行标题
            if ($line == 0) {
                continue;
            }
            //查找td标签
            preg_match_all($tdPattern, $tr, $tdResult);
            $tdList = $tdResult[2];
            //值得数量 跟标题数量不一样
            if (count($tdList) != $keyLength) {
                continue;
            }
            //键值对 合并
            $return[] = $this->formatData(array_combine($keys, $tdList));
        }
        return $return;
    }

    /**格式化采集数据
     * @param $data
     * @return array
     */
    public function formatData($data)
    {
        //获取字段对应数据类型
        $keys = collect(static::keys())->keyBy('en')->toArray();
        return collect($data)->map(function($item, $key) use ($keys) {
            if (array_key_exists($key, $keys)) {
                //数据类型
                $type = $keys[$key]['type'];
                switch($type) {
                    case 'string' :
                        $item = (string)$item;
                        break;
                    case 'float' :
                        $item = number_format((float)$item, 2, '.', '');
                        break;
                    case 'int' :
                        $item = (int)$item;
                        break;
                }
            }
            return $item;
        })->toArray();
    }


    public function all()
    {
        return $this->getTable();
    }
}


